C++

MFC 윈도우 GUI 프로그래밍 단기 속성 – 널널한 개발자 TV

 

https://www.youtube.com/watch?v=VPt69tFR4ww&list=PLXvgR_grOs1BEwuPXc0L7qm_11DeApwKJ&index=1

 


 

UI 와 자료 구조는 분리되어야 한다.

 


 

# 클래스의 상속 관계에서 생성자 호출은 자식 생성자부터 호출되지만 부모 생성자부터 실행된다.

# 생성자에서는 객체 자신을 초기화하는 작업 외에는 넣지 마라.

 


 

CDataA *pA = (CDataA*)new CDataC;
접근형식(참조형식) / 실형식
일반메서드는 파생클래스에서 재정의 하더라도 접근 형식을 따라 간다.
상위 클래스에서 함수를 가상화(virtual 을 붙이면) 시키면 파생 함수도 모두 가상 함수가 된다.
상위 클래스 일반 함수에서 가상 함수를 호출하면 파생 클래스의 함수가 호출 된다.

 


 

# Handle (HWND) : 식별자값 또는 포인터

 

# Document/View 체계

Frame Window (GUI) : Caption, Menu
View (GUI) : 내부 (클라이언트 윈도우)
Document : 자료구조
모든 걸 제어 : main 함수

– 세가지 구조
CMainFrame : GUI
C~~~View : GUI
C~~~Doc : 자료구조
C~~~App : 제어 체계

App -> InitInstance() : 메인함수의 시작으로 간주하자
App -> ExitInstance() : 메인함수의 끝부분

 


 

# 메뉴 추가
ID_MY_PAGE_USER_INPUT
이벤트 핸들러  추가

// cpp 파일 상단에 다이얼로그 클래스 파일을 include 시켜준다.

#include "CUserInputDlg.h"

void CMYMFCTEST1View::OnMyPageUserInput()
{
    CUserInputDlg dlg;
    if (dlg.DoModal() == IDOK)
    {
        AfxMessageBox(dlg.m_strUrl);
    }
}

 

 

# 새 다이얼로그 만들기
IDD_DIALOG_USER_INPUT
대화상자 클래스 추가 : CUserInputDlg (기본 클래스 CDialog)
가상 함수 -> OnInitDialog 추가 (초기화 작업)
OK 버튼 이벤트 핸들러 추가

 

// Control -> Variable
// DoDataExchange() 호출

UpdateData();

 

# 새 다이얼로그에 edit control 추가
IDC_EDIT_URL
변수 추가 : m_strURL
초기화는 생성자에서 한다.

 


 

전역 번수를 어디에서 선언하는게 좋을까?

App
Doc
View (교체 가능성 있음)
MainFrame

SDI : 문서 하나 뷰 여러개
MDI : 문서 뷰 1:1

# 전역변수는 App 이나 MainFrame 에 선언하는게 낫다.

# App 클래스에서 -> 변수 추가

CStringArray
m_arURL
public

// DECLARE_MESSAGE_MAP() 이 protected 매크로로 되어 있어서 접근성 오류가 난다.
m_arURL 변수를 public: 으로 위치로 옮겨준다.

다이얼로그 추가
IDD_DIALOG_HISTORY
클래스 추가 : CHistoryDlg (기본클래스 CDialog)
OnInitDialog() 추가 // 대화상자가 초기화되고 나타날 때

 

BOOL CHistoryDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    for (int i = 0; i < theApp.m_arURL.GetCount(); ++i)
    {
        m_listURL.AddString(theApp.m_arURL[i]);
    }
}

 

리스트 박스 추가
IDC_LIST_URL
변수 추가 m_listURL

메뉴 History 추가
이벤트 처리기 추가 (글로벌 수준이므로 MainFrame 이 좋겠다.)
(View 클래스, App 클래스, MainFrm 클래스 중에 가장 괜찮은 클래스 선택하자)

전역 변수를 쓰려면 App 클래스나 MainFrm 클래스가 좋다.

 

void CMainFrame::OnHistory()
{
    CHistoryDlg dlg;
    dlg.DoModal();
}

 

 


 

# 체크박스 추가
IDC_CHECK_ADD
변수 추가 : 값, m_bAdd
생성자에 FALSE로 되어 있는데 TRUE로 바꿔준다.

버튼이나 체크박스나 모두 버튼이다.

 

# 에디트 컨트롤
IDC_EDIT_SELECTED_ITEM
READ ONLY : TRUE
BORDER : FALSE
스태틱이랑 모양이 같지만 드래그가와 복붙이 가능해진다.
변수 추가 : m_strSelected (값, CString)

 

통지 메시지 (차일드 윈도우는 부모 윈도우를 통해서 접근)
리스트 박스 -> 클래스 마법사 -> 명령 -> 리스트박스 ID -> LBN_SELCHANGE (해당 다이얼로그 클래스에)

 

// 리스트 박스에서 아이템이 선택되면 에디트 컨트롤에 표시
void CHistoryDlg::OnSelchangeList1()
{
    int nIndex = m_listURL.GetCurSel();
    if (nIndex >= 0)
    {
        m_listURL.GetText(nIndex, m_strSelected);
        UpdateData(FALSE);  // 변수 -> 컨트롤
    }
}

 

리스트박스를 지우고 리스트컨트롤 추가
IDC_LIST_URL
View : Report
변수 추가 : m_listURL
초기화 작업은 onInitDialog() 에서..

 

BOOL CHistoryDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();	

    m_listURL.InsertColumn(0, _T("URL"), LVCFMT_LEFT, 400);

    m_listURL.SetExtendedStyle(m_listURL.GetExtendedStyle() |
        LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES |
        LVS_EX_TRACKSELECT | LVS_EX_UNDERLINEHOT);

    for (int i = 0; i < theApp.m_arURL.GetCount(); ++i)
    {
        m_listURL.InsertItem(i, theApp.m_arURL[i]);
    }

    return TRUE;
}

 

 

// 리스트 컨트롤의 아이템을 선택했을 때 에디트 컨트롤에 접근
void CHistoryDlg::OnLvnItemchangedListUrl(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    
    CString strTmp = m_listURL.GetItemText(0, 0);

    //1. 리소스 ID로 에디트 컨트롤에 접근
    //GetDlgItem(IDC_EDIT_SELECTED_ITEM)->SetWindowText(strTmp);

    //2. 에디트 컨트롤 변수 추가 (컨트롤)로 접근 (값, 컨트롤 두개를 만들었음)
    m_wndEdit.SetWindowText(strTmp);

    *pResult = 0;
}

 

 

 

 

 


 

“지원되지 않는 작업을 시도했습니다.” 메시지박스가 뜨면 리소스만 지웠다.
에디트 컨트롤만 지우면 리소스만 지운거지 코드상에는 남아있다.

 


 

Related posts

Leave a Comment